package com.han.spring.core.aop.aspectJ;

import static org.hamcrest.CoreMatchers.nullValue;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
* @author hanpeng
* @version 创建时间：2020年7月9日 上午10:37:30
* @ClassName 类名称
* @Description 类描述
*/
@Aspect
@Component
@Order(value=1)
public class MyLoggerAspect {
	@Pointcut(value="execution(* com.han.spring.core.aop.aspectJ.*.*(..))")
	public void pointCutExp() {
		//这里主要定义一个切点表达式 方便后面的引用 @Around(value="pointCutExp()")
	}
	
	/**
	 * @Before 方法设置为前置通知
	 * value   切入点表达式
	 * argNames
	 * demo  public int com.han.spring.core.aop.aspectJ.MathCalIml.add(int, int)
	 *       修饰符      返回值 包名                                                                     类名                     方法  方法参数===>称为方法签名
	 *       public int com.han.spring.core.aop.aspectJ.MathCalIml.*(int, int) *表示所有方法
	 *       * * com.han.spring.core.aop.aspectJ.MathCalIml.*(int, int)
	 *         * com.han.spring.core.aop.aspectJ.MathCalIml.*(int, int) 不限定修饰符和返回值
	 *         * com.han.spring.core.aop.aspectJ.MathCalIml.*(..)
	 *         * com.han.spring.core.aop.aspectJ.*.*(..)  com.han.spring.core.aop.aspectJ  包下的任意类的任意方法
	 *         返回值可以为空                                                          类名  方法名 .. 任意参数
	 * 
	 */
	/*@Before(value ="execution(public int com.han.spring.core.aop.aspectJ.MathCalIml.add(int, int))")
	public void before() {
		System.out.println("方法执行之前");
	}*/
	/**
	 * 可以加入一个参数 
	 */
	@Before(value ="execution(* com.han.spring.core.aop.aspectJ.*.*(..))")
	public void before(JoinPoint joinPoint) {
		Object[] args = joinPoint.getArgs();
		Signature signature = joinPoint.getSignature();
		System.out.println("方法执行之前");
	}
	@After(value="execution(* com.han.spring.core.aop.aspectJ.*.*(..))")
	public void after(JoinPoint joinPoint) {
		//写在finally 里面
		System.out.println("后置通知");
	}
	
	/**
	 * @param joint
	 * @param result
	 * 方法正常执行之后
	 * 如果要获取参数值 设置 returning="result"  作为切点的参数 保证名称一定一样
	 */
	@AfterReturning(value="execution(* com.han.spring.core.aop.aspectJ.*.*(..))",returning="result")
	public void afterReturn(JoinPoint joint,Object result) {
		// returning="result" 返回值的变量名称   Object result 返回值作为参数给这个参数
		//方法正常返回的通知 这个不一定执行
		System.out.println("返回通知 "+result);
	}
	
	/**
	 * @param ex
	 * 类似于接收返回值
	 * 可以设置形参的具体类型 只接受特定的异常以及子类
	 */
	@AfterThrowing(value="execution(* com.han.spring.core.aop.aspectJ.*.*(..))",throwing="ex")
	public void afterThrowing(Exception ex) {
		//方法正常返回的通知 这个不一定执行
		System.out.println("异常通知: "+ex.getMessage());
	}
	
	/**
	 * @param ex
	 * 类似于接收返回值
	 * 可以设置形参的具体类型 只接受特定的异常以及子类
	 * @throws Exception 
	 */
	@Around(value="pointCutExp()")
	public Object round(ProceedingJoinPoint joint) throws Exception {
		//方法正常返回的通知 这个不一定执行
		Object proceed=null;
		try {
			//前置通知
			proceed = joint.proceed();//执行方法
			//返回通知
		} catch (Throwable e) {
			e.printStackTrace();
			//异常通知
			throw new Exception(e.getMessage());
		}finally {
			//后置通知
		}
		System.out.println("环绕通知: ");
		return proceed;
	}
}
